﻿using System;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Geometry;

namespace AutoCAD_CSharp_plug_in3.Chap03
{
    public static class BlockHelper
    {
        /// <summary>
        /// </summary>
        /// <param name="spaceId"></param>
        /// <param name="blockName">块名称</param>
        /// <param name="posistion">插入点</param>
        /// <param name="scale">几何缩放倍数</param>
        /// <param name="rotateAngle">旋转角度</param>
        /// <param name="layerName">图层名称</param>
        /// <param name="checkBlockName">块名称检测</param>
        /// <param name="rec">组装块函数</param>
        public static void InsertBlockReference(this ObjectId spaceId, string blockName, Point3d posistion,
            Scale3d scale, double rotateAngle, string layerName,
            string checkBlockName, BlockTableRecord rec)
        {
            var db = HostApplicationServices.WorkingDatabase;
            var bt = (BlockTable)db.BlockTableId.GetObject(OpenMode.ForRead);

            if (!bt.Has(blockName) && blockName == checkBlockName) //如果没有该喷头模块则添加
            {
                bt.UpgradeOpen();
                bt.Add(rec);
                db.TransactionManager.AddNewlyCreatedDBObject(rec, true);
                //bt.DowngradeOpen();    
            }

            var btr = (BlockTableRecord)spaceId.GetObject(OpenMode.ForWrite);

            //创建喷头模块对象
            var br = new BlockReference(posistion, bt[blockName]);
            br.ScaleFactors = scale;
            br.LayerId = LayerUtils.GetLayer(db, layerName, 0);
            br.Rotation = rotateAngle;
            
            btr.AppendEntity(br);
            db.TransactionManager.AddNewlyCreatedDBObject(br, true);
            btr.DowngradeOpen();
        }

        //
        /// <summary>
        ///     计算多段线与块的最短距离
        /// </summary>
        /// <param name="pline">多段线</param>
        /// <param name="block">块</param>
        /// <returns></returns>
        public static double GetMinDistance(Polyline pline, BlockReference block)
        {
            var minDist = double.MaxValue;
            var blockPos = block.Position;

            for (var i = 0; i < pline.NumberOfVertices; i++)
            {
                var pt1 = pline.GetPoint3dAt(i);
                var pt2 = pline.GetPoint3dAt((i + 1) % pline.NumberOfVertices);
                // 线段离散化（每段取10个点）
                for (double t = 0; t <= 1; t += 0.1)
                {
                    var samplePt = pt1 + (pt2 - pt1) * t;
                    var dist = blockPos.DistanceTo(samplePt);
                    minDist = Math.Min(minDist, dist);
                }
            }

            return minDist;
        }


        public static bool IsPointInClosedPolyline(Polyline polyline, Point3d testPoint)
        {
            using (var tr = polyline.Database.TransactionManager.StartTransaction())
            {
                // 创建一个临时区域
                var curves = new DBObjectCollection();
                curves.Add(polyline);

                Region region = null;
                try
                {
                    var regions = new DBObjectCollection();
                    //Region.CreateFromCurves();
                    //Region.CreateFromCurves(curves, regions);

                    if (regions.Count > 0) region = regions[0] as Region;
                    // 判断点是否在区域内
                    //return region.IsPointInRegion(testPoint);
                }
                finally
                {
                    if (region != null)
                        region.Dispose();

                    // 清理临时对象
                    foreach (DBObject obj in curves)
                        obj.Dispose();
                }

                return false;
            }
        }
    }
}